package com.jwgf.smarowindingmachine_unity.ui;

import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.jwgf.Half485.modbusthreadpool.ModbusCommandManager;
import com.jwgf.adapter.MultiItemTypeAdapter;
import com.jwgf.common.ViewCache;
import com.jwgf.group.CraftDelegate;
import com.jwgf.group.Group;
import com.jwgf.group.GroupDelegate;
import com.jwgf.group.GroupMap;
import com.jwgf.mqtt.json.JsonBuilder;
import com.jwgf.objectbox.ObjectBox;
import com.jwgf.objectbox.SpindleParameter;
import com.jwgf.protocolstack.CommunicationStateListener;
import com.jwgf.protocolstack.ProtocolStack;
import com.jwgf.smarowindingmachine_unity.R;
import com.jwgf.smarowindingmachine_unity.logic.CanCommand;
import com.jwgf.smarowindingmachine_unity.logic.CommandGenerator;
import com.jwgf.smarowindingmachine_unity.logic.MachineParameterSharedPreference;
import com.jwgf.smarowindingmachine_unity.logic.SmaroWindingMachineDataAccessRules;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static com.jwgf.smarowindingmachine_unity.ui.SmaroWindingMachineActivity.canHandStack;

public class ParameterSettingGroupFragment extends BaseFragment implements View.OnFocusChangeListener, TextView.OnEditorActionListener, CommunicationStateListener.WriteFailedListener, CommunicationStateListener.WriteSucceedListener {
    private EditText spindleCount;
    private Button btnOK;
    private View v;
    private RecyclerView groupRecycler;
    private MultiItemTypeAdapter<Object> groupAdapter;
    private List<Object> groupList = new ArrayList<>();

    private RecyclerView craftRecycler;
    private MultiItemTypeAdapter<Object> craftAdapter;
    private List<Object> craftList = new ArrayList<>();

    private MachineParameterSharedPreference sp = MachineParameterSharedPreference.getInstance();

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        v = ViewCache.getInstance().getView(R.layout.fragment_parameter_setting_group);
        updateList();
        initViews();
        updateViews();
        JsonBuilder.stop();
        return v;
    }

    private void updateList() {
        groupList.clear();
        groupList.addAll(GroupMap.getInstance().getGroupList());
        craftList.clear();
        List<SpindleParameter> parameters = ObjectBox.get().boxFor(SpindleParameter.class).getAll();
        craftList.addAll(parameters);
    }

    private void initViews() {
        Button importBtn = v.findViewById(R.id.import_btn);
        importBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final String[] content = getExternalDevices();
                if (content == null) {
                    return;
                }
                ListDialogFragment listDialog = new ListDialogFragment();
                Bundle bd = new Bundle();
                bd.putStringArray(ListDialogFragment.ARRAY, content);
                listDialog.setArguments(bd);
                listDialog.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        final FileSelectedDialog fileSelectedDlg = new FileSelectedDialog();
                        Bundle bd = new Bundle();
                        bd.putString(FileSelectedDialog.ROOT_PATH, content[position]);
                        fileSelectedDlg.setArguments(bd);
                        fileSelectedDlg.setCallBack(new Runnable() {

                            @Override
                            public void run() {
                                Bundle bundle = new Bundle();
                                bundle.putString(CraftImportDialog.CRAFT_PATH, fileSelectedDlg.getPath());
                                CraftImportDialog dialog = new CraftImportDialog();
                                dialog.setArguments(bundle);
                                dialog.setCallback(new Runnable() {
                                    @Override
                                    public void run() {
                                        updateList();
                                        craftAdapter.notifyDataSetChanged();
                                    }
                                });
                                dialog.show(getFragmentManager(), "craft_select");

                            }
                        });
                        fileSelectedDlg.show(getFragmentManager(), "fileSelected");
                    }
                });
                listDialog.show(getFragmentManager(), "listDialog");
            }
        });
        Button exportBtn = v.findViewById(R.id.export_btn);
        exportBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CraftExportDialog dlg = new CraftExportDialog();
                dlg.show(getFragmentManager(), "craft_export");
            }
        });
        btnOK = v.findViewById(R.id.btn_ok);
        btnOK.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                canHandStack.putPriorityCmd(CanCommand.intAllGroup());
                WaitProgressDialog.show(getActivity());
            }
        });
        spindleCount = initEditTextOnCreate(R.id.spindle_count_value);
        groupRecycler = v.findViewById(R.id.group_recycler);
        groupAdapter = new MultiItemTypeAdapter<>(getActivity(), groupList);
        groupAdapter.addItemViewDelegate(new GroupDelegate());
        GridLayoutManager groupLayoutManager = new GridLayoutManager(getActivity(), 1);
        groupRecycler.setLayoutManager(groupLayoutManager);
        groupRecycler.setAdapter(groupAdapter);

        craftRecycler = v.findViewById(R.id.craft_recycler);
        craftAdapter = new MultiItemTypeAdapter<>(getActivity(), craftList);
        craftAdapter.addItemViewDelegate(new CraftDelegate());
        craftAdapter.setOnItemClickListener(new MultiItemTypeAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) {
                CraftCreateDialog dlg = new CraftCreateDialog();
                Bundle args = new Bundle();
                args.putLong(CraftCreateDialog.KEY, ((SpindleParameter)craftList.get(position)).id);
                dlg.setArguments(args);
                dlg.setCallback(new Runnable() {
                    @Override
                    public void run() {
                        // 如果删除了已经分配的批次，需要重新给分组匹配一个默认批次
                        GroupMap.getInstance().load();
                        updateList();
                        groupAdapter.notifyDataSetChanged();
                        craftAdapter.notifyDataSetChanged();
                    }
                });
                dlg.show(getFragmentManager(), "craft_dialog");
            }

            @Override
            public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position) {
                return false;
            }
        });
        GridLayoutManager craftLayoutManager = new GridLayoutManager(getActivity(), 1);
        craftRecycler.setLayoutManager(craftLayoutManager);
        craftRecycler.setAdapter(craftAdapter);


        EventBus.getDefault().register(this);
    }

    private void updateViews() {
        spindleCount.setText(sp.getValue(0x29, 0x01));
    }

    private void onSpindleCountModified() {
        int spindleCount = Integer.valueOf(sp.getValue(0x29, 0x01));
        int oldCount = GroupMap.getInstance().getSpindleCount();
        List<Integer> spindles = new ArrayList<>();
        if (oldCount < spindleCount) {
            for (int i = oldCount + 1; i <= spindleCount; ++i) {
                spindles.add(i);
            }
            long id = GroupMap.getInstance().getSpindleParameterIdFromSpindle(oldCount);
            GroupMap.getInstance().put(spindles, id);
        } else {
            for (int i = spindleCount + 1; i <= oldCount; ++i) {
                spindles.add(i);
            }
            GroupMap.getInstance().remove(spindles);
        }
        updateList();
        groupAdapter.notifyDataSetChanged();
    }

    private EditText initEditTextOnCreate(int id) {
        EditText editText = v.findViewById(id);
        editText.setSelectAllOnFocus(true);
        editText.setOnFocusChangeListener(this);
        editText.setOnEditorActionListener(this);
        editText.setBackgroundDrawable(null);
        return editText;
    }

    @Subscribe
    public void onGroupEdit(Group newGroup) {
        GroupMap.getInstance().put(newGroup.getSpindles(), newGroup.getId());
        updateList();
        groupAdapter.notifyDataSetChanged();
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        int id = v.getId();
        switch (id) {
            case R.id.spindle_count_value:
                if (!hasFocus) {
                    spindleCount.setText(sp.getValue(0x29, 0x01));
                }
                break;
        }
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        if (hidden) {
            canHandStack.unregisterWriteFailedListener(this);
            canHandStack.unregisterWriteSucceedListener(this);
            JsonBuilder.start();
        } else {
            updateList();
            groupAdapter.notifyDataSetChanged();
            craftAdapter.notifyDataSetChanged();
            JsonBuilder.stop();
        }
    }

    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            canHandStack.registerWriteFailedListener(this);
            canHandStack.registerWriteSucceedListener(this);
            String strValue = v.getText().toString();
            String key = "";
            boolean isValid = true;
            if (!TextUtils.isEmpty(strValue)) {
                switch (v.getId()) {
                    case R.id.spindle_count_value:
                        key = String.valueOf(0x29) + "-" + 1;
                        isValid = SmaroWindingMachineDataAccessRules.getInstance().isBetween(key, strValue);
                        if (isValid) {
                            canHandStack.putPriorityCmd(CanCommand.getBus());
                            canHandStack.putPriorityCmd(CanCommand.createAllCmd29(Integer.valueOf(strValue)));
                            canHandStack.putPriorityCmd(CanCommand.releaseBus());
                            WaitProgressDialog.show(getActivity());
                        }
                        break;
                }
                if (!isValid) {
                    canHandStack.unregisterWriteFailedListener(this);
                    canHandStack.unregisterWriteSucceedListener(this);
                    String max = SmaroWindingMachineDataAccessRules.getInstance().getDataAccessRule(key).getMax();
                    String min = SmaroWindingMachineDataAccessRules.getInstance().getDataAccessRule(key).getMin();
                    String warning = getResources().getString(R.string.range_warning);
                    warning = String.format(warning, min, max);
                    WarningDialog.show(getActivity(), warning);
                    updateViews();
                }
            }
        }
        return false;
    }


    @Override
    public void writeFailed(ProtocolStack ps, byte[] request) {
        short index = (short) (request[2] & 0xff);
        if (index == 0x29) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    updateViews();
                }
            });
        }
    }

    @Override
    public void writeSucceed(ProtocolStack ps, byte[] request) {
        short index = (short) (request[2] & 0xff);
        if (index == 0x29) {
            canHandStack.unregisterWriteFailedListener(this);
            canHandStack.unregisterWriteSucceedListener(this);
            sp.setValue(index, request);
            if (sp.getValue(MachineParameterSharedPreference.PLC_TYPE, "0").equals("0")) {
                byte[] data = {request[7], request[6]};
                ModbusCommandManager.getInstance().putPriorityCmd(CommandGenerator.createWriteCommand((byte) 1, 108, data));
            }


            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    updateViews();
                    onSpindleCountModified();
                }
            });

        }
    }

    private String[] getExternalDevices() {
        ArrayList<String> pathList = new ArrayList<String>();
        String path;
        if (Build.VERSION.RELEASE.equals("6.0.1")){
            path = "/mnt/media_rw/usb1";
        } else {
            path = "/mnt/usb1";
        }

        File file1 = new File(path);
        if (file1.exists()) {
            if (file1.list().length > 0) {
                pathList.add(path);
            }

            if (pathList.size() != 0) {
                return pathList.toArray(new String[]{});
            } else {
                return null;
            }
        }
        return null;

    }
}